using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using star_questionnair.Models;
using star_questionnair.Models.Enum;
using star_questionnairquestionnair.Services;
using Microsoft.Extensions.Logging;

namespace star_questionnair.Services.impl;

public class DifferenceSortQuestionAnalysisService : IDifferenceSortQuestionAnalysisService
{
        private readonly IQuestionService _questionService;
        private readonly IHistoryService _historyService;
        private readonly IUserService _userService;
        private readonly IResponseService _responseService;
        public DifferenceSortQuestionAnalysisService(
            IAnswerService answerService,
            IQuestionService questionService,
            IHistoryService historyService,
            IUserService userService,
            IResponseService responseService)
        {
            _questionService = questionService;
            _historyService = historyService;
            _userService = userService;
            _responseService = responseService;
        }
// 性别差异化分析
public async Task<Dictionary<bool, Dictionary<string, double>>> GetGenderDifferenceAsync(int questionId)
{
    var question = await _questionService.GetQuestionByIdAsync(questionId);
    if (!QuestionEnumExtensions.IsSortType(question.Type)) return null;

    var answers = _historyService.GetAnswersByQuestionId(questionId);
    var options = _historyService.GetOptionsByQuestionId(questionId);

    var totalScores = new Dictionary<bool, Dictionary<string, int>>();
    var countAnswers = new Dictionary<bool, Dictionary<string, int>>();

    foreach (var option in options)
    {
        totalScores[true] = new Dictionary<string, int>();
        totalScores[false] = new Dictionary<string, int>();
        countAnswers[true] = new Dictionary<string, int>();
        countAnswers[false] = new Dictionary<string, int>();
    }

    foreach (var answer in answers)
    {
        var response = await _responseService.GetResponseByIdAsync(answer.ResponseId);
        var user = await _userService.GetByIdAsync(response.UserId);
        var gender = user.Gender;

        var optionId = answer.Content.Trim();
        var option = options.FirstOrDefault(opt => opt.Id.ToString() == optionId);
        var optionContent = option != null ? option.Content : "Unknown";

        if (!totalScores[gender].ContainsKey(optionContent))
        {
            totalScores[gender][optionContent] = 0;
            countAnswers[gender][optionContent] = 0;
        }

        int position = answer.Sort;  // 排名
        int weight = options.Count + 1 - position;  // 权值计算

        totalScores[gender][optionContent] += weight;
        countAnswers[gender][optionContent] += 1;
    }

    var result = new Dictionary<bool, Dictionary<string, double>>();
    foreach (var gender in totalScores.Keys)
    {
        var genderResult = new Dictionary<string, double>();
        foreach (var option in totalScores[gender].Keys)
        {
            var totalScore = totalScores[gender][option];
            var count = countAnswers[gender][option];
            genderResult[option] = count == 0 ? 0.0 : (double)totalScore / count;
        }
        result[gender] = genderResult;
    }

    return result;
}

// 年龄差异化分析
public async Task<Dictionary<string, Dictionary<string, double>>> GetAgeDifferenceAsync(int questionId)
{
    var question = await _questionService.GetQuestionByIdAsync(questionId);
    if (!QuestionEnumExtensions.IsSortType(question.Type)) return null;

    var answers = _historyService.GetAnswersByQuestionId(questionId);
    var options = _historyService.GetOptionsByQuestionId(questionId);

    var totalScores = new Dictionary<string, Dictionary<string, int>>();
    var countAnswers = new Dictionary<string, Dictionary<string, int>>();

    var ageStages = new[] { "20-25", "25-30", "30-35", "35-40", "40-45", "45-50", "50+" };
    foreach (var ageStage in ageStages)
    {
        totalScores[ageStage] = new Dictionary<string, int>();
        countAnswers[ageStage] = new Dictionary<string, int>();
    }

    foreach (var answer in answers)
    {
        var response = await _responseService.GetResponseByIdAsync(answer.ResponseId);
        var user = await _userService.GetByIdAsync(response.UserId);
        var age = await _userService.CalculateUserAgeAsync(user.Id);

        var ageStage = GetAgeStage(age);

        if (ageStage != null)
        {
            var optionId = answer.Content.Trim();
            var option = options.FirstOrDefault(opt => opt.Id.ToString() == optionId);
            var optionContent = option != null ? option.Content : "Unknown";

            if (!totalScores[ageStage].ContainsKey(optionContent))
            {
                totalScores[ageStage][optionContent] = 0;
                countAnswers[ageStage][optionContent] = 0;
            }

            int position = answer.Sort;  // 排名
            int weight = options.Count + 1 - position;  // 权值计算

            totalScores[ageStage][optionContent] += weight;
            countAnswers[ageStage][optionContent] += 1;
        }
    }

    var result = new Dictionary<string, Dictionary<string, double>>();
    foreach (var ageStage in totalScores.Keys)
    {
        var ageStageResult = new Dictionary<string, double>();
        foreach (var option in totalScores[ageStage].Keys)
        {
            var totalScore = totalScores[ageStage][option];
            var count = countAnswers[ageStage][option];
            ageStageResult[option] = count == 0 ? 0.0 : (double)totalScore / count;
        }
        result[ageStage] = ageStageResult;
    }

    return result;
}

// 公司差异化分析
public async Task<Dictionary<string, Dictionary<string, double>>> GetEnterpriseDifferenceAsync(int questionId)
{
    var question = await _questionService.GetQuestionByIdAsync(questionId);
    if (!QuestionEnumExtensions.IsSortType(question.Type)) return null;

    var answers = _historyService.GetAnswersByQuestionId(questionId);
    var options = _historyService.GetOptionsByQuestionId(questionId);

    var totalScores = new Dictionary<string, Dictionary<string, int>>();
    var countAnswers = new Dictionary<string, Dictionary<string, int>>();

    foreach (var answer in answers)
    {
        var response = await _responseService.GetResponseByIdAsync(answer.ResponseId);
        var user = await _userService.GetByIdAsync(response.UserId);
        var company = user.Enterprise;

        var optionId = answer.Content.Trim();
        var option = options.FirstOrDefault(opt => opt.Id.ToString() == optionId);
        var optionContent = option != null ? option.Content : "Unknown";

        if (!totalScores.ContainsKey(company))
        {
            totalScores[company] = new Dictionary<string, int>();
            countAnswers[company] = new Dictionary<string, int>();
        }

        if (!totalScores[company].ContainsKey(optionContent))
        {
            totalScores[company][optionContent] = 0;
            countAnswers[company][optionContent] = 0;
        }

        int position = answer.Sort;  // 排名
        int weight = options.Count + 1 - position;  // 权值计算

        totalScores[company][optionContent] += weight;
        countAnswers[company][optionContent] += 1;
    }

    var result = new Dictionary<string, Dictionary<string, double>>();
    foreach (var company in totalScores.Keys)
    {
        var companyResult = new Dictionary<string, double>();
        foreach (var option in totalScores[company].Keys)
        {
            var totalScore = totalScores[company][option];
            var count = countAnswers[company][option];
            companyResult[option] = count == 0 ? 0.0 : (double)totalScore / count;
        }
        result[company] = companyResult;
    }

    return result;
}

// 职位差异化分析
public async Task<Dictionary<string, Dictionary<string, double>>> GetRoleDifferenceAsync(int questionId)
{
    var question = await _questionService.GetQuestionByIdAsync(questionId);
    if (!QuestionEnumExtensions.IsSortType(question.Type)) return null;

    var answers = _historyService.GetAnswersByQuestionId(questionId);
    var options = _historyService.GetOptionsByQuestionId(questionId);

    var totalScores = new Dictionary<string, Dictionary<string, int>>();
    var countAnswers = new Dictionary<string, Dictionary<string, int>>();

    foreach (var answer in answers)
    {
        var response = await _responseService.GetResponseByIdAsync(answer.ResponseId);
        var user = await _userService.GetByIdAsync(response.UserId);
        var position = user.RoleName;

        var optionId = answer.Content.Trim();
        var option = options.FirstOrDefault(opt => opt.Id.ToString() == optionId);
        var optionContent = option != null ? option.Content : "Unknown";

        if (!totalScores.ContainsKey(position))
        {
            totalScores[position] = new Dictionary<string, int>();
            countAnswers[position] = new Dictionary<string, int>();
        }

        if (!totalScores[position].ContainsKey(optionContent))
        {
            totalScores[position][optionContent] = 0;
            countAnswers[position][optionContent] = 0;
        }

        int answerPosition = answer.Sort;  // 排名
        int weight = options.Count + 1 - answerPosition;  // 权值计算

        totalScores[position][optionContent] += weight;
        countAnswers[position][optionContent] += 1;
    }

    var result = new Dictionary<string, Dictionary<string, double>>();
    foreach (var position in totalScores.Keys)
    {
        var positionResult = new Dictionary<string, double>();
        foreach (var option in totalScores[position].Keys)
        {
            var totalScore = totalScores[position][option];
            var count = countAnswers[position][option];
            positionResult[option] = count == 0 ? 0.0 : (double)totalScore / count;
        }
        result[position] = positionResult;
    }

    return result;
}

// 性别差异化分析
public async Task<Dictionary<bool, Dictionary<string, List<double>>>> GetGenderDifferenceAnalysisAsync(int questionId)
{
    var question = await _questionService.GetQuestionByIdAsync(questionId);
    if (!QuestionEnumExtensions.IsSortType(question.Type)) return null;

    var answers = _historyService.GetAnswersByQuestionId(questionId);
    var options = _historyService.GetOptionsByQuestionId(questionId);

    var genderSortCounts = new Dictionary<bool, Dictionary<string, int[]>>();

    // 初始化字典：按性别分组（true 为男性，false 为女性）
    foreach (var option in options)
    {
        genderSortCounts[true] = new Dictionary<string, int[]>();
        genderSortCounts[false] = new Dictionary<string, int[]>();

        genderSortCounts[true][option.Content] = new int[options.Count];
        genderSortCounts[false][option.Content] = new int[options.Count];

        Array.Fill(genderSortCounts[true][option.Content], 0);
        Array.Fill(genderSortCounts[false][option.Content], 0);
    }

    // 遍历每个回答，统计按性别分组的选项排序
    foreach (var answer in answers)
    {
        var response = await _responseService.GetResponseByIdAsync(answer.ResponseId);
        var user = await _userService.GetByIdAsync(response.UserId);
        var gender = user.Gender;

        var optionId = answer.Content.Trim();
        var option = options.FirstOrDefault(opt => opt.Id.ToString() == optionId);
        var optionContent = option?.Content ?? "Unknown";

        // 确保性别字典的内容存在
        if (!genderSortCounts.ContainsKey(gender))
        {
            genderSortCounts[gender] = new Dictionary<string, int[]>();
        }

        if (!genderSortCounts[gender].ContainsKey(optionContent))
        {
            genderSortCounts[gender][optionContent] = new int[options.Count];
            Array.Fill(genderSortCounts[gender][optionContent], 0);
        }

        var sortIndex = answer.Sort - 1; // 假设排序值是从1开始
        genderSortCounts[gender][optionContent][sortIndex]++;
    }

    // 计算每个选项的排序比例
    var result = new Dictionary<bool, Dictionary<string, List<double>>>();
    foreach (var gender in genderSortCounts.Keys)
    {
        var genderResult = new Dictionary<string, List<double>>();
        foreach (var optionContent in genderSortCounts[gender].Keys)
        {
            var counts = genderSortCounts[gender][optionContent];
            var total = counts.Sum();
            var proportions = counts.Select(count => total == 0 ? 0.0 : (double)count / total).ToList();
            genderResult[optionContent] = proportions;
        }
        result[gender] = genderResult;
    }

    return result;
}


        // 年龄差异化分析
        public async Task<Dictionary<string, Dictionary<string, List<double>>>> GetAgeDifferenceAnalysisAsync(int questionId)
        {
            var question = await _questionService.GetQuestionByIdAsync(questionId);
            if (!QuestionEnumExtensions.IsSortType(question.Type)) return null;

            var answers =  _historyService.GetAnswersByQuestionId(questionId);
            var options =  _historyService.GetOptionsByQuestionId(questionId);

            var ageSortCounts = new Dictionary<string, Dictionary<string, int[]>>();

            var ageStages = new[] { "20-25", "25-30", "30-35", "35-40", "40-45", "45-50", "50+" };
            foreach (var ageStage in ageStages)
            {
                ageSortCounts[ageStage] = new Dictionary<string, int[]>();

                foreach (var option in options)
                {
                    ageSortCounts[ageStage][option.Content] = new int[options.Count];
                    Array.Fill(ageSortCounts[ageStage][option.Content], 0);
                }
            }

            foreach (var answer in answers)
            {
                var response = await _responseService.GetResponseByIdAsync(answer.ResponseId);
                var user = await _userService.GetByIdAsync(response.UserId);
                var age = await _userService.CalculateUserAgeAsync(user.Id);

                var ageStage = GetAgeStage(age);
                if (ageStage != null)
                {
                    var optionId = answer.Content.Trim();
                    var option = options.FirstOrDefault(opt => opt.Id.ToString() == optionId);
                    var optionContent = option?.Content ?? "Unknown";

                    var sortIndex = answer.Sort - 1; // Assuming sort values are 1-based
                    ageSortCounts[ageStage][optionContent][sortIndex]++;
                }
            }

            var result = new Dictionary<string, Dictionary<string, List<double>>>();
            foreach (var ageStage in ageSortCounts.Keys)
            {
                var ageStageResult = new Dictionary<string, List<double>>();
                foreach (var optionContent in ageSortCounts[ageStage].Keys)
                {
                    var counts = ageSortCounts[ageStage][optionContent];
                    var total = counts.Sum();
                    var proportions = counts.Select(count => total == 0 ? 0.0 : (double)count / total).ToList();
                    ageStageResult[optionContent] = proportions;
                }
                result[ageStage] = ageStageResult;
            }

            return result;
        }

        // 公司差异化分析
        public async Task<Dictionary<string, Dictionary<string, List<double>>>> GetEnterpriseDifferenceAnalysisAsync(int questionId)
        {
            var question = await _questionService.GetQuestionByIdAsync(questionId);
            if (!QuestionEnumExtensions.IsSortType(question.Type)) return null;

            var answers =  _historyService.GetAnswersByQuestionId(questionId);
            var options =  _historyService.GetOptionsByQuestionId(questionId);

            var enterpriseSortCounts = new Dictionary<string, Dictionary<string, int[]>>();

            foreach (var answer in answers)
            {
                var response = await _responseService.GetResponseByIdAsync(answer.ResponseId);
                var user = await _userService.GetByIdAsync(response.UserId);
                var enterprise = user.Enterprise;

                var optionId = answer.Content.Trim();
                var option = options.FirstOrDefault(opt => opt.Id.ToString() == optionId);
                var optionContent = option?.Content ?? "Unknown";

                if (!enterpriseSortCounts.ContainsKey(enterprise))
                {
                    enterpriseSortCounts[enterprise] = new Dictionary<string, int[]>();
                }

                if (!enterpriseSortCounts[enterprise].ContainsKey(optionContent))
                {
                    enterpriseSortCounts[enterprise][optionContent] = new int[options.Count];
                    Array.Fill(enterpriseSortCounts[enterprise][optionContent], 0);
                }

                var sortIndex = answer.Sort - 1; // Assuming sort values are 1-based
                enterpriseSortCounts[enterprise][optionContent][sortIndex]++;
            }

            var result = new Dictionary<string, Dictionary<string, List<double>>>();
            foreach (var enterprise in enterpriseSortCounts.Keys)
            {
                var enterpriseResult = new Dictionary<string, List<double>>();
                foreach (var optionContent in enterpriseSortCounts[enterprise].Keys)
                {
                    var counts = enterpriseSortCounts[enterprise][optionContent];
                    var total = counts.Sum();
                    var proportions = counts.Select(count => total == 0 ? 0.0 : (double)count / total).ToList();
                    enterpriseResult[optionContent] = proportions;
                }
                result[enterprise] = enterpriseResult;
            }

            return result;
        }

        // 职位差异化分析
        public async Task<Dictionary<string, Dictionary<string, List<double>>>> GetRoleDifferenceAnalysisAsync(int questionId)
        {
            var question = await _questionService.GetQuestionByIdAsync(questionId);
            if (!QuestionEnumExtensions.IsSortType(question.Type)) return null;

            var answers =  _historyService.GetAnswersByQuestionId(questionId);
            var options =  _historyService.GetOptionsByQuestionId(questionId);

            var roleSortCounts = new Dictionary<string, Dictionary<string, int[]>>();

            foreach (var answer in answers)
            {
                var response = await _responseService.GetResponseByIdAsync(answer.ResponseId);
                var user = await _userService.GetByIdAsync(response.UserId);
                var role = user.RoleName;

                var optionId = answer.Content.Trim();
                var option = options.FirstOrDefault(opt => opt.Id.ToString() == optionId);
                var optionContent = option?.Content ?? "Unknown";

                if (!roleSortCounts.ContainsKey(role))
                {
                    roleSortCounts[role] = new Dictionary<string, int[]>();
                }

                if (!roleSortCounts[role].ContainsKey(optionContent))
                {
                    roleSortCounts[role][optionContent] = new int[options.Count];
                    Array.Fill(roleSortCounts[role][optionContent], 0);
                }

                var sortIndex = answer.Sort - 1; // Assuming sort values are 1-based
                roleSortCounts[role][optionContent][sortIndex]++;
            }

            var result = new Dictionary<string, Dictionary<string, List<double>>>();
            foreach (var role in roleSortCounts.Keys)
            {
                var roleResult = new Dictionary<string, List<double>>();
                foreach (var optionContent in roleSortCounts[role].Keys)
                {
                    var counts = roleSortCounts[role][optionContent];
                    var total = counts.Sum();
                    var proportions = counts.Select(count => total == 0 ? 0.0 : (double)count / total).ToList();
                    roleResult[optionContent] = proportions;
                }
                result[role] = roleResult;
            }

            return result;
        }

        private string GetAgeStage(int age)
        {
            if (age >= 20 && age <= 25) return "20-25";
            if (age > 25 && age <= 30) return "25-30";
            if (age > 30 && age <= 35) return "30-35";
            if (age > 35 && age <= 40) return "35-40";
            if (age > 40 && age <= 45) return "40-45";
            if (age > 45 && age <= 50) return "45-50";
            if (age > 50) return "50+";
            return null;
        }
}